package com.dtb.trade.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dtb.trade.dao.mysql.TradeDao;
import com.dtb.trade.entity.Block;
import com.dtb.trade.entity.PointDeal;
import com.dtb.trade.util.EncryptUtil;
import com.dtb.trade.util.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author:ChengJian
 * @Description:
 * @Date: Created in 下午5:27 2018/8/9
 */
@Service
public class TradeService {

    @Autowired
    TradeDao tradeDao;

    @Autowired
    RedisService redisService;

    //区块拥有交易记录的最大个数
    private static final int blockMax = 5;

    //该区块已经拥有的交易记录个数
    private static int blockNum = 0;

    //获取定时刷新的交易记录
    public List<PointDeal> gainAllTrade(){

        Map<String,Object> map = new HashMap<>();
        String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        map.put("start",today+" 00:00:00");
        map.put("end",today+" 23:59:59");
        return tradeDao.getAll(map);
    }

    //查询是否拥有数据块
    public boolean isBlock(){
        List<Block> list = tradeDao.isHave();
        if (list == null || list.isEmpty() || list.size()==0){
            return false;
        }
        return true;

    }

    //新增区块信息
    public boolean insertBlock(Block block){
        tradeDao.insertBlock(block);
        return true;
    }

    //更新区块信息
    public boolean updateBlock(Block block){
        tradeDao.updateBlock(block);
        return true;
    }

    //根据索引号查询区块信息
    public Block selectBlock(int index){
        return tradeDao.selectBlock(index);
    }

    //查询最新区块信息
    public Block getNewBlock(){
        Block block = tradeDao.getBlockIndex();

        block.setPointDeals(JSONObject.parseArray(block.getData(),PointDeal.class));

        return block;
    }

    //记账
    public boolean hyperledger(Block block,List<PointDeal> pointDeals){



        if (block != null && block.getPointDeals() != null){
            blockNum   = block.getPointDeals().size();
        }

        //准备记账的记忆记录个数
        int recordNum  = pointDeals.size();

        //欠缺，补足到最大区块个数
        int deficiency = blockMax - blockNum;

        //该区块是否能满足记账交易记录的个数，0刚好满足，正数绰绰有余，负数不满足，生成新的区块
        int surplusNum = deficiency-recordNum;

        if (blockNum < blockMax){
            //更新区块信息
            if (surplusNum >= 0){
                block.getPointDeals().addAll(pointDeals);
                block.setData(JSON.toJSONString(block.getPointDeals()));
                tradeDao.updateBlock(block);
            }else {
                //填补区块剩余
                for (int j =0;j<deficiency;j++){
                    block.getPointDeals().add(pointDeals.get(0));
                    pointDeals.remove(0);
                    //更新到数据库
                    block.setData(JSON.toJSONString(block.getPointDeals()));
                    tradeDao.updateBlock(block);
                    redisService.set("blockIndex",block.getIndex()+"");
                }
                //生成下一区块
                String nextPrev = block.getHash();
                int nextIndex   = block.getIndex()+1;
                int nextnonce   = block.getNonce();
                long nextTime   = System.currentTimeMillis();
                String nextHash = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());

                Block nextBlock = new Block();
                nextBlock.setTimestamp(nextTime);
                nextBlock.setPreviousHash(nextPrev);
                nextBlock.setHash(nextHash);
                nextBlock.setNonce(nextnonce);
                nextBlock.setIndex(nextIndex);
                hyperledgerTwo(nextBlock,pointDeals);
            }
        }else {
            //直接生成新区块
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            Block nextBlock = new Block();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);
            hyperledgerTwo(nextBlock,pointDeals);

        }

        return true;

    }

    //新区块记账
    public void hyperledgerTwo(Block block,List<PointDeal> pointDeals){

        int recordNum  = pointDeals.size();
        int deficiency = blockMax - blockNum;
        int surplusNum = deficiency-recordNum;

        if (surplusNum >= 0){
            //满足
            block.getPointDeals().addAll(pointDeals);
            block.setData(JSON.toJSONString(block.getPointDeals()));
            tradeDao.insertBlock(block);
            redisService.set("blockIndex",block.getIndex()+"");
        }else {
            //不满足
            for (int j =0;j<deficiency;j++){
                block.getPointDeals().add(pointDeals.get(0));
                pointDeals.remove(0);
            }
            block.setData(JSON.toJSONString(block.getPointDeals()));
            //更新到数据库
            tradeDao.insertBlock(block);

            //生成下一区块
            String nextPrev      = block.getHash();
            int nextIndex        = block.getIndex()+1;
            int nextnonce        = block.getNonce();
            long nextTime        = System.currentTimeMillis();
            String nextHash      = EncryptUtil.Encrypt(nextPrev+nextIndex+nextnonce+nextTime+block.getData());
            List<PointDeal> list = new ArrayList<>();

            Block nextBlock = new Block();
            nextBlock.setTimestamp(nextTime);
            nextBlock.setPreviousHash(nextPrev);
            nextBlock.setHash(nextHash);
            nextBlock.setNonce(nextnonce);
            nextBlock.setIndex(nextIndex);
            nextBlock.setPointDeals(list);

            hyperledgerTwo(nextBlock,pointDeals);
        }

    }

    //获取所有区块
    public List<Block> getAllBlock(){
        List<Block> blocks = tradeDao.isHave();
        if (blocks != null || blocks.size() > 0){
            return blocks;
        }
        return null;
     }



}
